/*******************************************************************************
SpriteKit.cpp

	Author:		LiuDingXi
	e-mail:		liudx@gmail.com
	Date time:	2009-08-06

	Copyright (C) 2009
	All rights reserved.
	
*******************************************************************************/
#include "StdAfx.h"
#include "SpriteKit.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

////////////////////////////////////////////////////////////////////////////////

CSpriteKit::CSpriteKit()
{
}

CSpriteKit::~CSpriteKit()
{
	Free();
}

BOOL CSpriteKit::Load(CArchive& ar)
{
	TCHAR szFolder[MAX_PATH];
	 _tcscpy(szFolder, ar.GetFile()->GetFilePath());
	 LPTSTR pTail = PathFindFileName(szFolder);
	 if(pTail)
	 {
		 *pTail = 0;
	 }

	GROUP* pGroup = NULL;
	SPRITE* pSprite = NULL;
	ACTION* pAction = NULL;
	FRAME* pFrame = NULL;
	
	CString s;
	while(ar.ReadString(s))
	{
		if(s.IsEmpty())
			continue;
		
		LPCTSTR p = s;
		MoveToBegin(p);
		
		#define IS_TAG(tag)	_tcsnicmp(p, tag, _tcslen(tag)) == 0
		
		if(IS_TAG(_T("group")))
		{
			pGroup = NewGroup(p + 5);
		}
		else if(IS_TAG(_T("image")))
		{
			if(pGroup != NULL)
			{
				pGroup->AddImage(p + 5, szFolder);
			}
		}
		else if(IS_TAG(_T("_draw")))
		{
			if(pGroup != NULL)
			{
				pGroup->AddDraw(p + 5);
			}
		}
		else if(IS_TAG(_T("sprite")))
		{
			pGroup = NULL;
			pSprite = NewSprite(p + 6);
		}
		else if(IS_TAG(_T("action")))
		{
			if(pSprite != NULL)
			{
				pAction = pSprite->AddAction(p + 6);
			}
		}
		else if(IS_TAG(_T("frame")))
		{
			if(pSprite && pAction)
			{
				pFrame = pAction->AddFrame(p);
			}
		}
		else if(IS_TAG(_T("fclip")))
		{
			if(pSprite && pFrame)
			{
				FCLIP* pFclip = pFrame->AddFclip(p);
				LinkImage(pFclip);
			}
		}
	}	
	return TRUE;
}

BOOL CSpriteKit::Store(CArchive& ar)
{
	list<GROUP*>::iterator git;
	git = m_Groups.begin();
	while(git != m_Groups.end())
	{
		GROUP* pGroup = *git++;
		
		CString szGroup(_T("group\t"));
		szGroup += pGroup->szName + _T("\t");
		szGroup += pGroup->szPath + _T("\r\n");
		
		ar.WriteString(szGroup);
		
		list<IMAGE*>::iterator it;
		it = pGroup->ImgList.begin();
		while(it != pGroup->ImgList.end())
		{
			IMAGE* pImage = *it++;

			if(pImage->nType == SceneDat::eImage)
			{
				CString szImage(_T("\timage\t"));
				szImage += pImage->szName + _T("\t");
				szImage += _T("\r\n");
				
				ar.WriteString(szImage);
			}
			else
			{
				CString szDraw(_T("\t_draw\t"));
				szDraw += pImage->szName + _T("\t");

				CString szParam;
				switch(pImage->nType)
				{
				case SceneDat::ePoint:
					szDraw += _T("point ");
					szParam.Format(_T("%d %d"), pImage->x, pImage->y);
					break;
				case SceneDat::eLine:
					szDraw += _T("line ");
					szParam.Format(_T("%d %d %d %d"), pImage->x, pImage->y, pImage->x2, pImage->y2);
					break;
				case SceneDat::eRect:
					szDraw += _T("rect ");
					szParam.Format(_T("%d %d %d %d"), pImage->x, pImage->y, pImage->cx, pImage->cy);
					break;
				case SceneDat::eRbox:
					szDraw += _T("rbox ");
					szParam.Format(_T("%d %d %d %d"), pImage->x, pImage->y, pImage->cx, pImage->cy);
					break;
				case SceneDat::eEllipse:
					szDraw += _T("ellipse ");
					szParam.Format(_T("%d %d %d %d"), pImage->x, pImage->y, pImage->cx, pImage->cy);
					break;
				case SceneDat::eCircle:
					szDraw += _T("circle ");
					szParam.Format(_T("%d %d %d"), pImage->x, pImage->y, pImage->r);
					break;
				case SceneDat::eArc:
					szDraw += _T("arc ");
					szParam.Format(_T("%d %d %d %d"), pImage->x, pImage->y, pImage->r, pImage->angles);
					break;
				case SceneDat::eText:
					break;
				}

				szDraw += szParam;
				szParam.Format(_T("\t%d %d %d %d"), pImage->style.nColor,
					pImage->style.nSize, pImage->style.nStyle, pImage->style.nOther);

				szDraw += _T("\r\n");
				
				ar.WriteString(szDraw);
			}
		}
	}
	
	CString szSeparate(_T("\r\n\r\n"));
	ar.WriteString(szSeparate);
	
	list<SPRITE*>::iterator sit;
	sit = m_Sprites.begin();
	while(sit != m_Sprites.end())
	{
		SPRITE* pSprite = *sit++;
		
		CString szSprite(_T("sprite\t"));
		szSprite += pSprite->szName;

		switch(pSprite->nFlags)
		{
		case SceneDat::SPF_NORMAL:
			break;
		}
		szSprite += _T("\r\n");
		
		ar.WriteString(szSprite);

		list<ACTION*>::iterator ait;
		ait = pSprite->ActionList.begin();
		while(ait != pSprite->ActionList.end())
		{
			ACTION* pAction = *ait++;
			CString szAction(_T("action\t"));
			szAction += pAction->szName;
			
			switch(pAction->nFlags)
			{
			case SceneDat::ACF_STATIC:
				szAction += _T("\tSTATIC");
				break;
			case SceneDat::ACF_ANIMATE:
				szAction += _T("\tANIMATE");
				break;
			case SceneDat::ACF_PLAY_LOOP:
				szAction += _T("\tPLAY_LOOP");
				break;
			case SceneDat::ACF_PLAY_ONCE:
				szAction += _T("\tPLAY_ONCE");
				break;
			}

			szAction += _T("\r\n");

			ar.WriteString(szAction);

			list<FRAME*>::iterator fit;
			fit = pAction->FrameList.begin();
			while(fit != pAction->FrameList.end())
			{
				FRAME* pFrame = *fit++;
				
				CString szFrame(_T("\tframe\t"));

				pFrame->ApplyDelay(true);

				//if(pFrame->nDelay > 0)
				//{
				CString szDelay;
				szDelay.Format(_T("%d"), pFrame->nDelay);
				szFrame += szDelay;
				//}

				
				LPCTSTR pName = pFrame->szName;
				CString szName = ParseOf(pName);
				ASSERT(szName == "frame");
				szDelay = ParseOf(pName);
				ASSERT( szDelay[0] == ':');
				CString szDescription = ParseOf(pName);
				if(szDescription.GetLength() > 0)
				{
					ASSERT(szDescription[0] == ':');
					LPCTSTR pDescription = szDescription;
					pDescription += 1;
					szFrame += _T('\t');
					szFrame += pDescription;
				}

				

				szFrame += _T("\r\n");
				
				ar.WriteString(szFrame);
				
				list<FCLIP*>::iterator it;
				it = pFrame->FclipList.begin();
				while(it != pFrame->FclipList.end())
				{
					FCLIP* pFclip = *it++;
					
					CString szFclip(_T("\t\tfclip\t"));
					szFclip += pFclip->szGroup + _T("\t");
					szFclip += pFclip->szImage + _T("\t");
					
					CString szParam;
					szParam.Format(_T("%d %d %d %d %d %d %.1f %d\r\n"),
						pFclip->nPosX, pFclip->nPosY,
						pFclip->nXRep, pFclip->nYRep,
						pFclip->nOffX, pFclip->nOffY,
						pFclip->fAngle, pFclip->bLock);
					
					ar.WriteString(szFclip);
					ar.WriteString(szParam);
					
				}
			}
		}
	}	
	return TRUE;
}

BOOL CSpriteKit::Free()
{
	if(m_Groups.size() > 0)
	{
		list<GROUP*>::iterator it;
		it = m_Groups.begin();
		while(it != m_Groups.end())
		{
			GROUP* pGroup = *it++;

			list<IMAGE*>::iterator lit;
			lit = pGroup->ImgList.begin();
			while(lit != pGroup->ImgList.end())
			{
				IMAGE* pImage = *lit++;
				delete pImage;
			}
			delete pGroup;
		}
		m_Groups.clear();
	}

	if(m_Sprites.size() > 0)
	{
		list<SPRITE*>::iterator it;
		it = m_Sprites.begin();
		while(it != m_Sprites.end())
		{
			SPRITE* pSprite = *it++;
			pSprite->Delete();
			delete pSprite;
		}
		m_Sprites.clear();
	}
	return TRUE;
}


BOOL CSpriteKit::LinkImage(CSpriteKit::FCLIP* pFclip)
{
	if(pFclip != NULL)
	{
		list<GROUP*>::iterator it;
		it = m_Groups.begin();
		while(it != m_Groups.end())
		{
			GROUP* pGroup = *it++;

			if(pGroup->szName == pFclip->szGroup)
			{
				list<IMAGE*>::iterator lit;
				lit = pGroup->ImgList.begin();
				while(lit != pGroup->ImgList.end())
				{
					IMAGE* pImage = *lit++;
					if(pImage->szName == pFclip->szImage)
					{
						pFclip->pImage = pImage;
						pFclip->Transfer();
						return TRUE;
					}
				}
			}
		}
	}
	return FALSE;
}


CSpriteKit::GROUP* CSpriteKit::NewGroup(LPCTSTR p)
{
	GROUP* pGroup = new GROUP;
	m_Groups.push_back(pGroup);

	pGroup->bExpand = TRUE;

	pGroup->szName = ParseOf(p);
	pGroup->szPath = ParseOf(p);

	return pGroup;
}

void CSpriteKit::GROUP::AddImage(LPCTSTR p, LPCTSTR szFolder)
{
	IMAGE* pImage = new IMAGE;

	pImage->pGroup = this;
	pImage->nType = SceneDat::eImage;

	pImage->szName = ParseOf(p);

	TCHAR szFileName[MAX_PATH];
	_tcscpy(szFileName, szFolder);
	PathAppend(szFileName, szPath);
	PathAppend(szFileName, pImage->szName);

	pImage->xImage.Load(szFileName);

	pImage->x = 0;
	pImage->y = 0;
	pImage->cx = pImage->xImage.GetWidth();
	pImage->cy = pImage->xImage.GetHeight();
	
	ImgList.push_back(pImage);
}


void CSpriteKit::GROUP::AddDraw(LPCTSTR p)
{
	IMAGE* pImage = new IMAGE;

	pImage->pGroup = this;

	pImage->szName = ParseOf(p);

	CString szType = ParseOf(p);

	if(_tcsicmp(szType, "point") == 0)
	{
		pImage->nType = SceneDat::ePoint;
		pImage->x = ParseOf(p, 0);
		pImage->y = ParseOf(p, 0);
	}
	else if(_tcsicmp(szType, "line") == 0)
	{
		pImage->nType = SceneDat::eLine;
		pImage->x = ParseOf(p, 0);
		pImage->y = ParseOf(p, 0);
		pImage->x2 = ParseOf(p, 0);
		pImage->y2 = ParseOf(p, 0);
	}
	else if(_tcsicmp(szType, "rect") == 0)
	{
		pImage->nType = SceneDat::eRect;
		pImage->x = ParseOf(p, 0);
		pImage->y = ParseOf(p, 0);
		pImage->cx = ParseOf(p, 0);
		pImage->cy = ParseOf(p, 0);
	}
	else if(_tcsicmp(szType, "rbox") == 0)
	{
		pImage->nType = SceneDat::eRbox;
		pImage->x = ParseOf(p, 0);
		pImage->y = ParseOf(p, 0);
		pImage->cx = ParseOf(p, 0);
		pImage->cy = ParseOf(p, 0);
	}
	else if(_tcsicmp(szType, "ellipse") == 0)
	{
		pImage->nType = SceneDat::eEllipse;
		pImage->x = ParseOf(p, 0);
		pImage->y = ParseOf(p, 0);
		pImage->cx = ParseOf(p, 0);
		pImage->cy = ParseOf(p, 0);
	}
	else if(_tcsicmp(szType, "circle") == 0)
	{
		pImage->nType = SceneDat::eRbox;
		pImage->x = ParseOf(p, 0);
		pImage->y = ParseOf(p, 0);
		pImage->r = ParseOf(p, 0);
	}
	else if(_tcsicmp(szType, "arc") == 0)
	{
		pImage->nType = SceneDat::eRbox;
		pImage->x = ParseOf(p, 0);
		pImage->y = ParseOf(p, 0);
		pImage->r = ParseOf(p, 0);
		
		int nBeginAngle = ParseOf(p, 0);
		int nEndAngle = ParseOf(p, 0);

		nBeginAngle = nBeginAngle % 360;
		nEndAngle = nEndAngle % 360;

		pImage->angles = (nBeginAngle << 16) | nEndAngle;
	}
	else if(_tcsicmp(szType, "text") == 0)
	{
		pImage->nType = SceneDat::eRbox;
		pImage->x = ParseOf(p, 0);
		pImage->y = ParseOf(p, 0);
		pImage->cx = ParseOf(p, 0);
		pImage->cy = ParseOf(p, 0);
	}
	else
	{
		pImage->nType = SceneDat::ePoint;
	}

	pImage->style.nColor = ParseOf(p, 0);
	pImage->style.nSize  = ParseOf(p, 0);
	pImage->style.nStyle = ParseOf(p, 0);
	pImage->style.nOther = ParseOf(p, 0);
	
	ImgList.push_back(pImage);
}

CSpriteKit::SPRITE* CSpriteKit::NewSprite(LPCTSTR p)
{
	SPRITE* pSprite = new SPRITE;
	m_Sprites.push_back(pSprite);

	pSprite->szName = ParseOf(p);

	pSprite->nFlags = SceneDat::SPF_NORMAL;

	CString szFlag = ParseOf(p);
	if(szFlag == _T("NORMAL"))
	{
		pSprite->nFlags = SceneDat::SPF_NORMAL;
	}
	return pSprite;
}

bool CSpriteKit::DelSprite(CSpriteKit::SPRITE* pSprite)
{
	list<SPRITE*>::iterator it;
	it = m_Sprites.begin();
	while(it != m_Sprites.end())
	{
		SPRITE* p = *it;
		if(p == pSprite)
		{
			pSprite->Delete();
			m_Sprites.erase(it);
			delete pSprite;
			return true;
		}
		it++;
	}
	return false;
}

CSpriteKit::ACTION* CSpriteKit::SPRITE::AddAction(LPCTSTR p)
{
	ACTION* pAction = new ACTION;

	pAction->szName = ParseOf(p);

	pAction->nFlags = SceneDat::ACF_ANIMATE;

	CString szFlag = ParseOf(p);
	if(szFlag == _T("STATIC"))
	{
		pAction->nFlags = SceneDat::ACF_STATIC;
	}
	else if(szFlag == _T("ANIMATE"))
	{
		pAction->nFlags = SceneDat::ACF_ANIMATE;
	}
	else if(szFlag == _T("PLAY_LOOP"))
	{
		pAction->nFlags = SceneDat::ACF_PLAY_LOOP;
	}
	else if(szFlag == _T("PLAY_ONCE"))
	{
		pAction->nFlags = SceneDat::ACF_PLAY_ONCE;
	}
	else
	{
		pAction->nFlags = SceneDat::ACF_ANIMATE;
	}
	
	ActionList.push_back(pAction);

	return pAction;
}


bool CSpriteKit::SPRITE::DelAction(CSpriteKit::ACTION* pAction)
{
	list<ACTION*>::iterator it;
	it = ActionList.begin();
	while(it != ActionList.end())
	{
		ACTION* p = *it;
		if(p == pAction)
		{
			ActionList.erase(it);
			pAction->Delete();
			delete pAction;
			return true;
		}
		it++;
	}
	return false;	
}


void CSpriteKit::SPRITE::Delete()
{
	list<ACTION*>::iterator it;
	it = ActionList.begin();
	while(it != ActionList.end())
	{
		ACTION* pAction = *it++;
		pAction->Delete();
		delete pAction;
	}
}

void CSpriteKit::SPRITE::OnDraw(CDC* pDC, int x, int y, int zoom)
{
	ACTION* pAction = GetAction(nActive);
	if(pAction)
	{
		pAction->OnDraw(pDC, x, y, zoom);
	}
}

void CSpriteKit::SPRITE::OnDraw2(CDC* pDC, int x, int y, int cx, int cy)
{
	ACTION* pAction = GetAction(nActive);
	if(pAction)
	{
		pAction->OnDraw2(pDC, x, y, cx, cy);
	}
}


void CSpriteKit::SPRITE::OnUpdate()
{
	ACTION* pAction = GetAction(nActive);
	if(pAction)
	{
		pAction->OnUpdate();
	}
}

bool CSpriteKit::SPRITE::HitTest(int x, int y)const
{
	ACTION* pAction = GetAction(nActive);
	if(pAction)
	{
		return pAction->HitTest(x, y);
	}
	return false;
}

void CSpriteKit::SPRITE::GetRect(RECT& rect)const
{
	ACTION* pAction = GetAction(nActive);
	if(pAction)
	{
		pAction->GetRect(rect);
	}
}

CSpriteKit::ACTION* CSpriteKit::SPRITE::GetAction(int nIndex)const
{
	list<ACTION*>::const_iterator it;
	it = ActionList.begin();
	while(it != ActionList.end())
	{
		ACTION* pAction = *it++;
		if(nIndex <= 0)
			return pAction;

		nIndex--;
	}
	return NULL;
}

CString CSpriteKit::SPRITE::GetSprite()
{
	CString szSprite;
	szSprite = szName;

	switch(nFlags)
	{
	case SceneDat::SPF_NORMAL:
		break;
	}
	szSprite += _T("\r\n");
	return szSprite;
}

CSpriteKit::FRAME* CSpriteKit::ACTION::AddFrame(LPCTSTR p)
{
	FRAME* pFrame = new FRAME;

	pFrame->szName = ParseOf(p);
	pFrame->nDelay = ParseOf(p, 0);
	
	CHAR buf[256];
	itoa(pFrame->nDelay, buf, 10);
	pFrame->szName += " :";
	pFrame->szName += buf;

	CString description = ParseOf(p);
	if(description.GetLength() > 0)
	{
		pFrame->szName += " :";
		pFrame->szName += description;
	}

	FrameList.push_back(pFrame);

	return pFrame;
}

bool CSpriteKit::ACTION::DelFrame(CSpriteKit::FRAME* pFrame)
{
	list<FRAME*>::iterator it;
	it = FrameList.begin();
	while(it != FrameList.end())
	{
		FRAME* p = *it;
		if(p == pFrame)
		{
			FrameList.erase(it);
			pFrame->Delete();
			delete pFrame;
			return true;
		}
		it++;
	}
	return false;	
}

void CSpriteKit::ACTION::Delete()
{
	list<FRAME*>::iterator fit;
	fit = FrameList.begin();
	while(fit != FrameList.end())
	{
		FRAME* pFrame = *fit++;
		pFrame->Delete();
		delete pFrame;
	}
}

void CSpriteKit::ACTION::OnDraw(CDC* pDC, int x, int y, int zoom)
{
	FRAME* pFrame = GetFrame(nActive);
	if(pFrame)
	{
		pFrame->OnDraw(pDC, x, y, zoom);
	}
}

void CSpriteKit::ACTION::OnDraw2(CDC* pDC, int x, int y, int cx, int cy)
{
	FRAME* pFrame = GetFrame(nActive);
	if(pFrame)
	{
		pFrame->OnDraw2(pDC, x, y, cx, cy);
	}
}

CSpriteKit::FRAME* CSpriteKit::ACTION::GetFrame(int nIndex)const
{
	list<FRAME*>::const_iterator it;
	it = FrameList.begin();
	while(it != FrameList.end())
	{
		FRAME* pFrame = *it++;
		if(nIndex <= 0)
			return pFrame;

		nIndex--;
	}
	return NULL;
}

void CSpriteKit::ACTION::OnUpdate()
{
	nActive++;
	if(nActive >= FrameList.size())
	{
		nActive = 0;
	}
}

bool CSpriteKit::ACTION::HitTest(int x, int y)const
{
	FRAME* pFrame = GetFrame(nActive);
	if(pFrame)
	{
		return pFrame->HitTest(x, y);
	}

	return false;
}

void CSpriteKit::ACTION::GetRect(RECT& rect)const
{
	FRAME* pFrame = GetFrame(nActive);
	if(pFrame)
	{
		pFrame->GetRect(rect);
	}
}

CString CSpriteKit::ACTION::GetAction()
{
	CString szAction;
	szAction = szName;

	switch(nFlags)
	{
	case SceneDat::ACF_STATIC:
		break;
	case SceneDat::ACF_ANIMATE:
		szAction += _T("\tANIMATE");
		break;
	case SceneDat::ACF_PLAY_LOOP:
		szAction += _T("\tPLAY_LOOP");
		break;
	case SceneDat::ACF_PLAY_ONCE:
		szAction += _T("\tPLAY_ONCE");
		break;
	}
	szAction += _T("\r\n");
	return szAction;
}

CSpriteKit::FCLIP* CSpriteKit::FRAME::AddFclip(LPCTSTR p)
{
	FCLIP* pFclip = new FCLIP;

	pFclip->szName = ParseOf(p);
	pFclip->szGroup = ParseOf(p);
	pFclip->szImage = ParseOf(p);

	pFclip->nPosX = ParseOf(p, 0);
	pFclip->nPosY = ParseOf(p, 0);

	pFclip->nXRep = ParseOf(p, 1);
	pFclip->nYRep = ParseOf(p, 1);

	pFclip->nOffX = ParseOf(p, 0);
	pFclip->nOffY = ParseOf(p, 0);

	if(pFclip->nXRep < 1)
		pFclip->nXRep = 1;
	if(pFclip->nYRep < 1)
		pFclip->nYRep = 1;

	pFclip->fAngle = ParseOf(p, 0.0f);
	pFclip->pTrans = NULL;

	pFclip->bLock = ParseOf(p, 0);

	pFclip->pImage = NULL;

	FclipList.push_back(pFclip);

	return pFclip;
}

bool CSpriteKit::FRAME::DelFclip(CSpriteKit::FCLIP* pFclip)
{
	list<FCLIP*>::iterator it;
	it = FclipList.begin();
	while(it != FclipList.end())
	{
		FCLIP* p = *it;
		if(p == pFclip)
		{
			FclipList.erase(it);
			delete pFclip;
			return true;
		}
		it++;
	}
	return false;	
}

void CSpriteKit::FRAME::Delete()
{
	if(FclipList.size() > 0)
	{
		list<FCLIP*>::iterator it;
		it = FclipList.begin();
		while(it != FclipList.end())
		{
			FCLIP* p = *it++;
			delete p;
		}
		FclipList.clear();
	}
}

void CSpriteKit::FRAME::OnDraw(CDC* pDC, int x, int y, int zoom)
{
	list<FCLIP*>::iterator it;
	it = FclipList.begin();
	while(it != FclipList.end())
	{
		FCLIP* pFclip = *it++;
		pFclip->OnDraw(pDC, x, y, zoom);
	}	
}


void CSpriteKit::FRAME::OnDraw2(CDC* pDC, int x, int y, int cx, int cy)
{
	list<FCLIP*>::iterator it;
	it = FclipList.begin();
	while(it != FclipList.end())
	{
		FCLIP* pFclip = *it++;
		pFclip->OnDraw2(pDC, x, y, cx, cy);
	}	
}

bool CSpriteKit::FRAME::HitTest(int x, int y)const
{
	list<FCLIP*>::const_iterator it;
	it = FclipList.begin();
	while(it != FclipList.end())
	{
		FCLIP* pFclip = *it++;
		if(pFclip->HitTest(x, y))
		{
			return true;
		}
	}
	return false;
}

void CSpriteKit::FRAME::GetRect(RECT& rect)const
{
	list<FCLIP*>::const_iterator it;
	it = FclipList.begin();
	if(it != FclipList.end())
	{
		FCLIP* pFclip = *it++;
		pFclip->GetRect(rect);

		while(it != FclipList.end())
		{
			FCLIP* pFclip = *it++;
			RECT rc = {0, 0, 0, 0};
			pFclip->GetRect(rc);

			if(rc.left < rect.left)
				rect.left = rc.left;
			if(rc.right > rect.right)
				rect.right = rc.right;
			if(rc.top < rect.top)
				rect.top = rc.top;
			if(rc.bottom > rect.bottom)
				rect.bottom = rc.bottom;
		}
	}
}

void CSpriteKit::FRAME::Offset(int x, int y)
{
	list<FCLIP*>::const_iterator it;
	it = FclipList.begin();
	while(it != FclipList.end())
	{
		FCLIP* pFclip = *it++;
		pFclip->nPosX += x;
		pFclip->nPosY += y;
	}
}

void CSpriteKit::FRAME::FlipY()
{
	RECT rect;
	GetRect(rect);

	list<FCLIP*>::const_iterator it;
	it = FclipList.begin();
	while(it != FclipList.end())
	{
		FCLIP* pFclip = *it++;

		RECT rc;
		pFclip->GetRect(rc);

		int cx = rc.left - rect.left;
		int cw = rc.right - rc.left;

		if(pFclip->fAngle == 360.0f)
		{
			pFclip->fAngle = 0.0f;
			pFclip->Transfer();
		}
		else
		{
			pFclip->fAngle = 360.0f;
			pFclip->Transfer();
		}

		pFclip->nPosX = rect.right - cx - cw;
	}
}


CString CSpriteKit::FRAME::GetFrame()
{
	CString szFrame(_T("\tframe\t"));
	if(nDelay > 0)
	{
		CString szDelay;
		szDelay.Format(_T("%d"), nDelay);
		szFrame += szDelay;
	}
	szFrame += _T("\r\n");
	return szFrame;
}

void CSpriteKit::FRAME::ApplyDelay(bool checkSame)
{
	LPCTSTR pName = szName;
	ParseOf(pName);
	CString pDelay = ParseOf(pName);
	ASSERT(pDelay[0] == ':');
	LPCTSTR strDelay = pDelay;
	strDelay += 1;
	int delay = atoi(strDelay);
	if(checkSame)
	{
		ASSERT(delay == nDelay);
	}
	nDelay = delay;

	//head descript
	CString s_descript = ParseOf(pName);
	if(s_descript.GetLength() > 0)
	{
		ASSERT(s_descript[0] == ':');
	}
}
CSpriteKit::FCLIP::~FCLIP()
{
	if(pTrans != NULL)
	{
		delete pTrans;
		pTrans = NULL;
	}
}

SIZE CSpriteKit::FCLIP::GetSize()const
{
	SIZE sz = {0, 0};

	CxImage* pxImage = GetImage();
	if(pxImage)
	{
		sz.cx = pxImage->GetWidth();
		sz.cy = pxImage->GetHeight();
	}
	return sz;
}

void CSpriteKit::FCLIP::GetRect(RECT& rect)const
{
	rect.top = rect.left = rect.right = rect.bottom = 0;

	CxImage* pxImage = GetImage();
	if(pxImage)
	{
		rect.left = nPosX;
		rect.top = nPosY;
		rect.right = nPosX + pxImage->GetWidth() * nXRep;
		rect.bottom = nPosY + pxImage->GetHeight() * nYRep;
	}
}

void CSpriteKit::FCLIP::Transfer()
{
	if(pTrans != NULL)
	{
		delete pTrans;
		pTrans = NULL;
	}
	if(pImage->nType == SceneDat::eImage && fAngle > 0.0f)
	{
		pTrans = new CxImage;
		if(fAngle == 180.0f)
		{
			pImage->xImage.Rotate180(pTrans);
		}
		else if(fAngle == 90.0f)
		{
			pImage->xImage.RotateRight(pTrans);
		}
		else if(fAngle == 270.0f)
		{
			pImage->xImage.RotateLeft(pTrans);
		}
		else if(fAngle == 360.0f)
		{
			pTrans->Copy(pImage->xImage);
			pTrans->Mirror();
		}
		else
		{
			if(!pImage->xImage.AlphaIsValid())
			{
				pImage->xImage.AlphaCreate();
			}
			pImage->xImage.Rotate2(fAngle, pTrans);
		}
	}
}

CxImage* CSpriteKit::FCLIP::GetImage()const
{
	if(pTrans)
		return pTrans;
	if(pImage && pImage->nType == SceneDat::eImage)
	{
		return &(pImage->xImage);
	}
	return NULL;
}

void CSpriteKit::FCLIP::DrawPoint(CDC* pDC, int x, int y, int zoom)
{
}
void CSpriteKit::FCLIP::DrawLine(CDC* pDC, int x, int y, int zoom)
{
	int x1 = x + pImage->x;
	int y1 = y + pImage->y;
	int x2 = x + pImage->x2;
	int y2 = y + pImage->y2;
	pDC->MoveTo(x1, y1);
	pDC->LineTo(x2, y2);
}
void CSpriteKit::FCLIP::DrawRect(CDC* pDC, int x, int y, int zoom)
{
	int x1 = x + pImage->x;
	int y1 = y + pImage->y;
	int x2 = x1 + pImage->cx;
	int y2 = y1 + pImage->cy;
	pDC->Rectangle(x1, y1, x2, y2);
}
void CSpriteKit::FCLIP::DrawRbox(CDC* pDC, int x, int y, int zoom)
{
}
void CSpriteKit::FCLIP::DrawEllipse(CDC* pDC, int x, int y, int zoom)
{
}
void CSpriteKit::FCLIP::DrawCircle(CDC* pDC, int x, int y, int zoom)
{
}
void CSpriteKit::FCLIP::DrawArc(CDC* pDC, int x, int y, int zoom)
{
}
void CSpriteKit::FCLIP::DrawText(CDC* pDC, int x, int y, int zoom)
{
}

void CSpriteKit::FCLIP::OnDraw(CDC* pDC, int x, int y, int zoom)
{
	CxImage* pxImage = GetImage();
	if(pxImage)
	{
		if(zoom == 0)
		{
			x += nPosX;
			y += nPosY;
			int w = nOffX > 0 ? nOffX : pxImage->GetWidth();
			int h = nOffY > 0 ? nOffY : pxImage->GetHeight();

			for(int i=0; i<nXRep; i++)
			{
				for(int j=0; j<nYRep; j++)
				{
					pxImage->Draw(pDC->GetSafeHdc(), x, y + j*h);
				}
				x += w;
			}
		}
		else if(zoom > 0)
		{
			int w = nOffX > 0 ? nOffX : pxImage->GetWidth();
			int h = nOffY > 0 ? nOffY : pxImage->GetHeight();

			for(int i=0; i<nXRep; i++)
			{
				for(int j=0; j<nYRep; j++)
				{
					int zx = x + (nPosX + w*i) * zoom;
					int zy = y + (nPosY + h*j) * zoom;
					int zw = w * zoom;
					int zh = h * zoom;
					pxImage->Draw(pDC->GetSafeHdc(), zx, zy, zw, zh);
				}
			}
		}
		else if(zoom < 0)
		{

		}
	}
	else // draw 
	{
		if(zoom == 0)
		{
			x += nPosX;
			y += nPosY;
		}

		switch(pImage->nType)
		{
		case SceneDat::ePoint:
			DrawPoint(pDC, x, y, zoom);
			break;
		case SceneDat::eLine:
			DrawLine(pDC, x, y, zoom);
			break;
		case SceneDat::eRect:
			DrawRect(pDC, x, y, zoom);
			break;
		case SceneDat::eRbox:
			DrawRbox(pDC, x, y, zoom);
			break;
		case SceneDat::eEllipse:
			DrawEllipse(pDC, x, y, zoom);
			break;
		case SceneDat::eCircle:
			DrawCircle(pDC, x, y, zoom);
			break;
		case SceneDat::eArc:
			DrawArc(pDC, x, y, zoom);
			break;
		}
	}
}

void CSpriteKit::FCLIP::OnDraw2(CDC* pDC, int x, int y, int cx, int cy)
{
	CxImage* pxImage = GetImage();
	if(pxImage)
	{
		x += nPosX;
		y += nPosY;
		int w = nOffX > 0 ? nOffX : pxImage->GetWidth();
		int h = nOffY > 0 ? nOffY : pxImage->GetHeight();

		for(int i=0; i<nXRep; i++)
		{
			for(int j=0; j<nYRep; j++)
			{
				pxImage->Draw2(pDC->GetSafeHdc(), x, y + j*h, cx, cy);
			}
			x += w;
		}
	}
	else
	{

	}
}

bool CSpriteKit::FCLIP::HitTest(int x, int y)const
{
	if(x >= nPosX && y >= nPosY)
	{
		CxImage* pxImage = GetImage();
		if(pxImage)
		{
			int w = nPosX + pxImage->GetWidth() * nXRep;
			int h = nPosY + pxImage->GetHeight() * nYRep;

			if(x < w && y < h)
				return true;
		}
	}
	return false;
}

CString CSpriteKit::FCLIP::GetFclip()
{
	CString szFclip(_T("\t\tfclip\t"));
	szFclip += szGroup + _T("\t");
	szFclip += szImage + _T("\t");
	
	CString szParam;
	szParam.Format(_T("%d %d %d %d %d %d %.1f %d\r\n"),
		nPosX, nPosY,
		nXRep, nYRep,
		nOffX, nOffY,
		fAngle, bLock);

	szFclip += szParam;
	return szFclip;
}

CSpriteKit::SPRITE* CSpriteKit::FindSprite(LPCTSTR szName)
{
	list<SPRITE*>::iterator it;
	it = m_Sprites.begin();
	while(it != m_Sprites.end())
	{
		SPRITE* pSprite = *it++;
		if(pSprite->szName == szName)
		{
			return pSprite;
		}
	}
	return NULL;
}


void CSpriteKit::GetImages(set<IMAGE*>& ImgSet)
{
	list<GROUP*>::iterator it;
	it = m_Groups.begin();
	while(it != m_Groups.end())
	{
		GROUP*	pGroup = *it++;

		list<IMAGE*>::iterator lit;
		lit = pGroup->ImgList.begin();
		while(lit != pGroup->ImgList.end())
		{
			IMAGE*	pImage = *lit++;
			ImgSet.insert(pImage);
		}
	}
}


int CSpriteKit::JoinTo(list<CSpriteKit::IMAGE*>& refList)
{
	int nCount = 0;
	list<GROUP*>::iterator it;
	it = m_Groups.begin();
	while(it != m_Groups.end())
	{
		GROUP* pGroup = *it++;
		refList.insert(refList.end(), 
			pGroup->ImgList.begin(),
			pGroup->ImgList.end());

		nCount += pGroup->ImgList.size();
	}
	return nCount;
}

int CSpriteKit::JoinTo(list<CSpriteKit::FCLIP*>& refList)
{
	int nCount = 0;
	list<SPRITE*>::iterator it;
	it = m_Sprites.begin();
	while(it != m_Sprites.end())
	{
		SPRITE* pSprite = *it++;

		list<ACTION*>::iterator ait;
		ait = pSprite->ActionList.begin();
		while(ait != pSprite->ActionList.end())
		{
			ACTION* pAction = *ait++;

			list<FRAME*>::iterator fit;
			fit = pAction->FrameList.begin();
			while(fit != pAction->FrameList.end())
			{
				FRAME* pFrame = *fit++;

				refList.insert(refList.end(),
					pFrame->FclipList.begin(),
					pFrame->FclipList.end());

				nCount += pFrame->FclipList.size();
			}
		}
	}
	return nCount;	
}

int CSpriteKit::JoinTo(list<CSpriteKit::FRAME*>& refList)
{
	int nCount = 0;
	list<SPRITE*>::iterator it;
	it = m_Sprites.begin();
	while(it != m_Sprites.end())
	{
		SPRITE* pSprite = *it++;

		list<ACTION*>::iterator ait;
		ait = pSprite->ActionList.begin();
		while(ait != pSprite->ActionList.end())
		{
			ACTION* pAction = *ait++;

			refList.insert(refList.end(),
				pAction->FrameList.begin(),
				pAction->FrameList.end());

			nCount += pAction->FrameList.size();
		}
	}
	return nCount;	
}


int CSpriteKit::JoinTo(list<CSpriteKit::ACTION*>& refList)
{
	int nCount = 0;
	list<SPRITE*>::iterator it;
	it = m_Sprites.begin();
	while(it != m_Sprites.end())
	{
		SPRITE* pSprite = *it++;

		refList.insert(refList.end(),
			pSprite->ActionList.begin(),
			pSprite->ActionList.end());

		nCount += pSprite->ActionList.size();
	}
	return nCount;	
}


int CSpriteKit::JoinTo(list<CSpriteKit::SPRITE*>& refList)
{
	int nCount = 0;

	refList.insert(refList.end(),
		m_Sprites.begin(),
		m_Sprites.end());

	nCount += m_Sprites.size();

	return nCount;	
}
